
\chapter{Files}


An executing {\bf T} system interacts with the world outside by
communicating with various external entities, including:

\begin{itemize}
\item[{}]    {\it people\/}, via keyboards and displays;

\item[{}]    \iix{file systems}, via operating system calls, possibly over
    a communications network;

\item[{}]    and {\it processes\/}, running on the same machine or on different machines.
\end{itemize}

The language provides simple standardized interfaces to the first
two of these.  Particular implementations may provide more complete
interfaces.

Standard access to a terminal is provided by the ports {\tt TERMINAL-INPUT}
and {\tt TERMINAL-OUTPUT} (page \pageref{TERMINAL-INPUT}).
Access to file systems is provided by the facilities described in this
chapter.

\section{File systems}


A \iix{file system} is a collection of named permanent objects called
\iix{files}, and a mechanism for manipulating this collection.
A \iix{file system object} is a {\bf T} object which names
or represents an actual file system.  Where the distinction is
unimportant, a file system object is referred to simply as a file
system.

A given {\bf T} implementation may provide access to multiple file
systems; such a facility is not described in this manual.  However,
one may assume that at least one file system, known as the
\iix{local file system}, is accessible.

\index{LOCAL-FS@{\tt LOCAL-FS}}
{\mbox {\tt (LOCAL-FS) $\longrightarrow$\  {\it file-system\/}}}
\hfill  

\begin{inset}{}
Returns the local file system object.
\end{inset} 

The following type predicates are defined to query the type of a file
system.

\index{AEGIS-FS?@{\tt AEGIS-FS?}}
{\mbox {\tt (AEGIS-FS? {\it file-system\/}) $\longrightarrow$\  {\it boolean\/}}}
\hfill Type predicate

\begin{inset}{}
Returns true if {\it file-system\/} represents an Aegis file system.
\end{inset} 

\index{UNIX-FS?@{\tt UNIX-FS?}}
{\mbox {\tt (UNIX-FS? {\it file-system\/}) $\longrightarrow$\  {\it boolean\/}}}
\hfill Type predicate

\begin{inset}{}
Returns true if {\it file-system\/} represents a Unix file system.
\end{inset} 

\index{VMS-FS?@{\tt VMS-FS?}}
{\mbox {\tt (VMS-FS? {\it file-system\/}) $\longrightarrow$\  {\it boolean\/}}}
\hfill Type predicate

\begin{inset}{}
Returns true if {\it file-system\/} represents a VMS file system.
\end{inset} 

\section{Filenames}


A \iix{filename} is an object which names a file.
Filenames are immutable record structures with the following
components:

\begin{itemize}
\item[{}]{\it File system:\/} the file system object via which the named file is
accessible.

\item[{}]{\it Directory:\/} a collection of files within the file system
to which the named file belongs.

\item[{}]{\it Name:\/} the name of the file within the directory, or of a family
of files, as further specified by the file type and generation components
of the filename.

\item[{}]{\it Type:\/} the type of the file (also known as ``extension'').

\item[{}]{\it Generation:\/} a positive integer specifying a particular version
or incarnation of the file.  Larger generation numbers indicate newer
versions.
\end{itemize}

In general, the directory, name, and type components of a file
are usually symbols, the file system component is a file system
object, and the generation component is an integer.
The file system component may be a symbol which names a file system
in an implementation-dependent manner.

Filenames may be incompletely specified; missing components
are represented by having null (false) as their value.  An omitted
file system is usually interpreted to be the same as the local file system,
an omitted directory component means the current working directory.
The name component may not be omitted.

The external representation of a filename has the form
\begin{codexenv}
\#[Filename {\it file-system dir name type gen\/}]
\end{codexenv}
where {\it gen\/} and {\it type\/} may be omitted, if null.

\index{MAKE-FILENAME@{\tt MAKE-FILENAME}}
{\mbox {\tt (MAKE-FILENAME {\it file-system dir name type gen\/}) $\longrightarrow$\  {\it filename\/}}}
\hfill  
\\ {\mbox {\tt (MAKE-FILENAME {\it file-system dir name {\rm .} type\/}) $\longrightarrow$\  {\it filename\/}}}

\begin{inset}{} 

Returns a filename.  The arguments become the components of the filename
object.  {\it Type\/} and {\it gen\/} may be omitted, in which case they default to
null (absent).
\end{inset}

\index{-{\tt >}FILENAME@{\tt -{\tt >}FILENAME}}
{\mbox {\tt (-{\tt >}FILENAME {\it filespec\/}) $\longrightarrow$\  {\it filename\/}}}
\hfill  

\label{to-filename}
\begin{inset}{}
Coerces \iix{filespec} to a filename.
\begin{itemize}
\item[{}]If {\it filespec\/} is a filename, then it is returned.

\item[{}]If {\it filespec\/} is a list {\it l\/}, then {\tt MAKE-FILENAME} is called,
passing null as the file system argument, and the elements of
the list as the rest of the arguments.

\item[{}]If {\it filespec\/} is a symbol {\it x\/}, then it is treated the same
as the list {\tt (() {\it x\/})}.

\item[{}]If {\it filespec\/} is a string, then it is converted to a filename
in an implementation-dependent way, such that {\tt FILENAME-{\tt >}STRING}
applied to the filename will return a string which is equal
to {\it filespec\/}.
\end{itemize}

For example:
\begin{codexenv}
    \begin{tabular}{lll}
-$>$FILENAME '(MATH FACT T))               &$\Longrightarrow$\ &  \#[Filename () MATH FACT T] \\
-$>$FILENAME '(MATH FACT))                 &$\Longrightarrow$\ &  \#[Filename () MATH FACT] \\
-$>$FILENAME 'FACT)                        &$\Longrightarrow$\ &  \#[Filename () () FACT] \\
-$>$FILENAME "fact.t")                     &$\Longrightarrow$\ &  \#[Filename () () FACT T]
\end{tabular}
    \end{codexenv}
The last example is plausible, but it will not necessarily hold in
all {\bf T} implementations, since the coercion of strings to filenames
is not defined here.  
\end{inset} 

\index{FILENAME?@{\tt FILENAME?}}
{\mbox {\tt (FILENAME? {\it object\/}) $\longrightarrow$\  {\it boolean\/}}}
\hfill Type predicate

\begin{inset}{}
Returns true if {\it object\/} is a filename.
\end{inset} 

\index{FILENAME-FS@{\tt FILENAME-FS}}
{\mbox {\tt (FILENAME-FS {\it filename\/}) $\longrightarrow$\  {\it file-system\/} {\rm or} {\it false\/}}}
\hfill  

\begin{inset}{}
Returns the file system component of {\it filename\/}, or false (null)
if it has none.
\end{inset} 

\index{FILENAME-DIR@{\tt FILENAME-DIR}}
{\mbox {\tt (FILENAME-DIR {\it filename\/}) $\longrightarrow$\  {\it symbol\/} {\rm or} {\it false\/}}}
\hfill  

\begin{inset}{}
Returns the directory component of {\it filename\/}.
\end{inset} 

\index{FILENAME-NAME@{\tt FILENAME-NAME}}
{\mbox {\tt (FILENAME-NAME {\it filename\/}) $\longrightarrow$\  {\it symbol\/}}}
\hfill  

\begin{inset}{}
Returns the name component of {\it filename\/}.
\begin{codexenv}
(FILENAME-NAME '\#[Filename () MATH FACT T])  $\Longrightarrow$\   FACT
\end{codexenv}
\end{inset} 

\index{FILENAME-TYPE@{\tt FILENAME-TYPE}}
{\mbox {\tt (FILENAME-TYPE {\it filename\/}) $\longrightarrow$\  {\it symbol\/} {\rm or} {\it false\/}}}
\hfill  

\begin{inset}{}
Returns the type component of {\it filename\/}.
\end{inset} 

\index{FILENAME-GENERATION@{\tt FILENAME-GENERATION}}
{\mbox {\tt (FILENAME-GENERATION {\it filename\/}) $\longrightarrow$\  {\it integer\/} {\rm or} {\it false\/}}}
\hfill  

\begin{inset}{}
Returns the generation component of {\it filename\/}.
\end{inset} 

\index{FILENAME-{\tt >}STRING@{\tt FILENAME-{\tt >}STRING}}
{\mbox {\tt (FILENAME-{\tt >}STRING {\it filename\/}) $\longrightarrow$\  {\it string\/}}}
\hfill  

\begin{inset}{}
Returns a string representing {\it filename\/} in the native syntax
of {\it filename\/}'s file system (or of the local file system if
{\it filename\/} is null).

If the directory component of {\it filename\/} is a symbol,
then it is interpreted as a ``logical name'' in a manner idiosyncratic
to the type of the file system:
\begin{itemize}
\item[{}]    Aegis: a {\bf T} logical name is interpreted as being a link in the
    naming directory.

\item[{}]    Unix: a {\bf T} logical name is an environment variable.

\item[{}]    VMS: a {\bf T} logical name is a VMS logical name.
\end{itemize}
For example:
\begin{codexenv}
(FILENAME-$>$STRING '\#[Filename AN-AEGIS-FS MATH FACT T]) \\
  $\Longrightarrow$\   "$\tilde{}$math/fact.t" \\
(FILENAME-$>$STRING '\#[Filename A-UNIX-FS MATH FACT T]) \\
  $\Longrightarrow$\   "/usr/math/fact.t" \\
(FILENAME-$>$STRING '\#[Filename A-VMS-FS MATH FACT T]) \\
  $\Longrightarrow$\   "MATH:FACT.T" \\
\end{codexenv}
(In the Unix example, we assume that environment variable {\tt MATH} was
defined to be {\tt /usr/math}, e.g. by a ``{\tt setenv MATH /usr/math}''
shell command.)
\end{inset} 

\section{Files}


A \iix{file} is an external permanent object stored in a file system.
Files are accessed in {\bf T} via ports.
Ordinarily, files are sequences of characters, similar to strings.
An input port open on an existing file delivers successive characters
(or lines, or parsed objects) out of the file.  An output port open
on a new file deposits successive characters (or lines, or printed
representations of objects) into the file.

{\tt OPEN} and {\tt MAYBE-OPEN} obtain ports which access files.
Any port created by {\tt OPEN} or {\tt MAYBE-OPEN} should be closed
(using the {\tt CLOSE} operation, page \pageref{CLOSE})
when no further access to the file is required.  This is guaranteed
if {\tt OPEN} and {\tt MAYBE-OPEN} are always used in conjunction with
{\tt WITH-OPEN-PORTS} (page \pageref{WITH-OPEN-PORTS}), which ensures
that any port opened actually gets closed, even if there is a throw
out of the body of the {\tt WITH-OPEN-PORTS} form.

\index{OPEN@{\tt OPEN}}
{\mbox {\tt (OPEN {\it filespec mode-list\/}) $\longrightarrow$\  {\it port\/}}}
\hfill  

\label{OPEN}
\begin{inset}{}
Opens an external file for reading or for writing, and returns
a port which accesses it.
{\it Filespec\/} should be a filename or any other object which can
be coerced to one (see {\tt -{\tt >}FILENAME}, page \pageref{to-filename}).
{\it Mode-list\/} should be
a list of keywords (symbols) specifying what kind of
access to the file is desired.
The only keywords currently recognized are {\tt IN}, {\tt OUT}, and
{\tt APPEND}, indicating reading, writing, and appending, respectively.
It is an error condition if the file cannot be opened for some reason.
{\tt \begin{tabbing}
(WITH-OPEN-PORTS \= ((PORT (OPEN file.txt '(IN)))) \\
  \> (READ-LINE PORT))
\end{tabbing}}
\end{inset} 

\index{MAYBE-OPEN@{\tt MAYBE-OPEN}}
{\mbox {\tt (MAYBE-OPEN {\it filespec modes\/}) $\longrightarrow$\  {\it port\/} {\rm or} {\it false\/}}}
\hfill  

\begin{inset}{}
Like {\tt OPEN}, but returns false if for any reason it
cannot open the file.
\end{inset} 

\index{PORT-NAME@{\tt PORT-NAME}}
{\mbox {\tt (PORT-NAME {\it port\/}) $\longrightarrow$\  {\it filename\/}}}
\hfill Operation

\begin{inset}{}
\index{PORT-NAME@{\tt PORT-NAME}}
Returns the filename of the file on which {\it port\/} is open.
This operation is not handled by any system-created ports other than
those created by {\tt OPEN} and {\tt MAYBE-OPEN}.
\end{inset} 

\index{FILE-EXISTS?@{\tt FILE-EXISTS?}}
{\mbox {\tt (FILE-EXISTS? {\it filespec\/}) $\longrightarrow$\  {\it boolean\/}}}
\hfill  

\begin{inset}{}
Returns true if the specified file exists.
\end{inset} 

\index{FILE-MOVE@{\tt FILE-MOVE}}
{\mbox {\tt (FILE-MOVE {\it source-filespec\/} {\it dest-filespec\/}) $\longrightarrow$\  {\it undefined\/}}}
\hfill  

\begin{inset}{}
Moves the file named by {\it source-filespec\/} to a new location given by
{\it dest-filespec\/}.
In some cases, this operation can be performed without actually
copying the file, for example, if the two locations are on the same
``volume'' of the same file system.  In this case, {\tt FILE-MOVE}
is simply a rename operation.  In other cases, it may be more expensive.
    \begin{inset}{Bug:}
    Not all versions of {\bf T} 3.1 implement {\tt FILE-MOVE}.
    \end{inset}
\end{inset} 

\index{FILE-DELETE@{\tt FILE-DELETE}}
{\mbox {\tt (FILE-DELETE {\it filespec\/}) $\longrightarrow$\  {\it undefined\/}}}
\hfill  

\begin{inset}{}
Deletes the specified file.
    \begin{inset}{Bug:}
    Not all versions of {\bf T} 3.1 implement {\tt FILE-DELETE}.
    \end{inset}
\end{inset} 
